﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;

namespace LowLevelGraphics.ColorSpaces
{
    /// <summary>
    /// LMS Channel
    /// </summary>
    public enum LMSChannel
    {
        /// <summary>
        /// 
        /// </summary>
        L = 0,
        /// <summary>
        /// 
        /// </summary>
        M = 1,
        /// <summary>
        /// 
        /// </summary>
        S = 2
    }

    /// <summary>
    /// LMS color space
    /// </summary>
    [DebuggerDisplay("L: {m_L}, M: {m_M}, S: {m_S}")]
    public class LMS : AbstractColorSpace
    {
        protected double m_L = 0.0f;
        protected double m_M = 0.0f;
        protected double m_S = 0.0f;

        /// <summary>
        /// Primary cnstructor
        /// </summary>
        /// <param name="_color"></param>
        public LMS(Color _color)
            : base(_color)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LMS"/> class.
        /// </summary>
        /// <param name="_L">The _ L.</param>
        /// <param name="_M">The _ M.</param>
        /// <param name="_S">The _ S.</param>
        public LMS(double _L, double _M, double _S)
        {
            m_L = _L;
            m_M = _M;
            m_S = _S;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_lms"></param>
        internal LMS(LMS _lms)
        {
            this.m_L = _lms.m_L;
            this.m_M = _lms.m_M;
            this.m_S = _lms.m_S;
        }

        /// <summary>
        /// Enables you to cast rgb in this color space
        /// </summary>
        /// <param name="_color"></param>
        /// <returns></returns>
        public static explicit operator LMS(Color _color)
        {
            return new LMS(_color);
        }

        /// <summary>
        /// Gets or sets L
        /// </summary>
        public double L
        {
            get { return m_L; }
            set { m_L = value; }
        }

        /// <summary>
        /// Gets or sets M
        /// </summary>
        public double M
        {
            get { return m_M; }
            set { m_M = value; }
        }

        /// <summary>
        /// Gets or sets S
        /// </summary>
        public double S
        {
            get { return m_S; }
            set { m_S = value; }
        }

        /// <summary>
        /// converts rgb into this color space
        /// </summary>
        protected override void CalcValues()
        {
            CIEXYZ ciexyz = new CIEXYZ(m_Color);
            m_L = 0.8951 * ciexyz.X + 0.2664 * ciexyz.Y - 0.1614 * ciexyz.Z;
            m_M = -0.7502 * ciexyz.X + 1.7135 * ciexyz.Y + 0.0367 * ciexyz.Z;
            m_S = 0.0389 * ciexyz.X - 0.0685 * ciexyz.Y + 1.0296 * ciexyz.Z;
        }

        /// <summary>
        /// retransform back to rgb color space
        /// </summary>
        /// <returns></returns>
        public override Color ToColor()
        {
            double r = 0.0f;
            double g = 0.0f;
            double b = 0.0f;

            return Color.FromArgb((int)r, (int)g, (int)b);
        }

        /// <summary>
        /// Gets the values.
        /// </summary>
        /// <returns></returns>
        public override object[] GetValues()
        {
            return new object[] { m_L, m_M, m_S };
        }

        /// <summary>
        /// Sets the values.
        /// </summary>
        /// <param name="_aObject">The _a object.</param>
        public override void SetValues(object[] _aObject)
        {
            this.m_L = (double)_aObject[0];
            this.m_M = (double)_aObject[1];
            this.m_S = (double)_aObject[2];
        }

        /// <summary>
        /// Used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new LMS(this);
        }

    }
}
